/***********************************************************************************
Copy right:	    Coffee Tech.
Author:         jiaoyue
Date:           2018-12-26
Description:    文件处理封装
***********************************************************************************/

#include "file_opt.h"

//FILE *fp不能设计成全局打开一次，每一个操作都可能针对不同的打开方式
//这里只做封装，不做通用性
BOOL fileopt_exist(const char *pathname)
{
    int ret;
    ret = access(pathname, F_OK);
    if(ret == 0)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

long fileopt_getsize(const char *path)
{
    FILE *fp;
    long filesize = -1;
    fp = fopen(path, "r");
    if (fp == NULL)
    {
        return filesize;
    }
    fseek(fp, 0L, SEEK_END);
    filesize = ftell(fp);
    fclose(fp);
    return filesize;
}

/**
 * @brief 读取所有文件内容，这个方法要提供缓冲区，
 * 但是缓冲区大小需要先调用上个接口自己确定，这里并不检查是否越界
 * @param path
 * @param ret_buf
 * @return 实际读到的字节数目
 */
size_t fileopt_readall(const char *path, char *ret_buf)
{
    FILE *fp;
    size_t sum = 0, nbytes;
    char buf[256];

    if ((fp = fopen(path, "r")) == NULL)
    {
        return sum;
    }

    while (1)
    {
        nbytes = fread(buf, 1, 256, fp);
        if (nbytes > 0)
        {
            strncpy(ret_buf, buf, nbytes); //这里只针对文本
            ret_buf += nbytes;
            sum += nbytes;
        }
        else
        {
            break;
        }
    }

    fclose(fp);
    return sum;
}


size_t file_opt_read(const char *path, char *buf, size_t buf_sz)
{
    FILE *fp;
    size_t nbytes = 0;

    if ((fp = fopen(path, "r")) == NULL)
    {
        return 0;
    }

    nbytes = fread(buf, 1, buf_sz, fp);
    fclose(fp);
    return nbytes;
}


int find_files_by_name_strict(char *basePath, char *file_name, char *buf, int buf_sz)
{
    DIR *dir;
    struct dirent *ptr;
    char base[1000];
    char path[KB];

    if ((dir=opendir(basePath)) == NULL)
    {
        perror("Open dir error...");
        exit(1);
    }

    while ((ptr=readdir(dir)) != NULL)
    {
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
        {
            continue;
        }
        else if(ptr->d_type == 8)//file
        {
            if (strcmp(file_name, ptr->d_name) == 0)
            {
                sprintf(path, "%s/%s\n", basePath, ptr->d_name);
                if (strlen(path)+strlen(buf) < buf_sz)
                {
                    strcat(buf, path);
                }
            }
        }
        else if(ptr->d_type == 10)//link file
        {
            if (strcmp(file_name, ptr->d_name) == 0)
            {
                sprintf(path, "%s/%s\n", basePath, ptr->d_name);
                if (strlen(path)+strlen(buf) < buf_sz)
                {
                    strcat(buf, path);
                }
            }
        }
        else if(ptr->d_type == 4)//dir
        {
            memset(base,'\0',sizeof(base));
            strcpy(base,basePath);
            strcat(base,"/");
            strcat(base,ptr->d_name);
            find_files_by_name_strict(base, file_name, buf, buf_sz-strlen(buf));
        }
    }
    closedir(dir);
    return 1;
}


int find_files_by_name_weak(char *basePath, char *file_name, char *buf, int buf_sz)
{
    DIR *dir;
    struct dirent *ptr;
    char base[1000];
    char path[KB];

    //printf("goto find_files_by_name_weak\n");
    if ((dir=opendir(basePath)) == NULL)
    {
        perror("Open dir error...");
        return -1;
    }

    while ((ptr=readdir(dir)) != NULL)
    {
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
        {
            continue;
        }
        else if(ptr->d_type == 8)//file
        {
            if (strstr(ptr->d_name, file_name))
            {
                sprintf(path, "%s/%s\n", basePath, ptr->d_name);
                if (strlen(path)+strlen(buf) < buf_sz)
                {
                    strcat(buf, path);
                }
            }
        }
        else if(ptr->d_type == 10)//link file
        {
            if (strstr(ptr->d_name, file_name))
            {
                sprintf(path, "%s/%s\n", basePath, ptr->d_name);
                if (strlen(path)+strlen(buf) < buf_sz)
                {
                    strcat(buf, path);
                }
            }
        }
        else if(ptr->d_type == 4)//dir
        {
            memset(base,'\0',sizeof(base));
            strcpy(base,basePath);
            strcat(base,"/");
            strcat(base,ptr->d_name);
            find_files_by_name_weak(base, file_name, buf, buf_sz-strlen(buf));
        }
    }
    closedir(dir);
    return 0;
}


int find_dirs_by_name_weak(char *basePath, char *dir_name, char *buf, int buf_sz)
{
    DIR *dir;
    struct dirent *ptr;
    char base[1000];

    //printf("goto find_files_by_name_weak\n");
    if ((dir=opendir(basePath)) == NULL)
    {
        perror("Open dir error...");
        return -1;
    }

    while ((ptr=readdir(dir)) != NULL)
    {
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
        {
            continue;
        }
        else if(ptr->d_type == 4)//dir
        {
            memset(base,'\0',sizeof(base));
            strcpy(base,basePath);
            strcat(base,"/");
            strcat(base,ptr->d_name);

            if (strstr(ptr->d_name, dir_name))
            {
                strcat(buf, base);
                strcat(buf, "\n");
            }

            find_files_by_name_weak(base, dir_name, buf, buf_sz-strlen(buf));
        }
    }
    closedir(dir);
    return 0;
}


int file_opt_read_by_line(const char *path, char buf[][MAX_PROC_NAME_SZ], size_t buf_sz, size_t line_sz)
{
    FILE *fp;
    int line_num = 0;

    if (NULL == buf)
    {
        return 0;
    }

    if ((fp = fopen(path, "r")) == NULL)
    {
        return 0;
    }

    for (line_num=0; line_num < line_sz; line_num++)
    {
        if (NULL == fgets(buf[line_num], buf_sz-1, fp))
        {
            break;
        }
        //printf("buf[%d]=%s\n", line_num, buf[line_num]);
    }
    fclose(fp);
    return line_num;
}


size_t file_opt_write(const char *path, char *dat, size_t dat_len)
{
    FILE *fp;
    size_t ret= 0;

    if (!dat || dat_len == 0)
    {
        return 0;
    }

    fp = fopen(path, "w");
    if (!fp)
    {
        return 0;
    }

    ret = fwrite(dat, 1, dat_len, fp);
    fclose(fp);
    return ret;
}





